import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository,Not } from 'typeorm';
import { Bk_Product } from './bk_product.entity';
import { join } from 'path';
import * as fs from 'fs';
import { Bk_Product_Info } from 'src/product_info/product_info.entity';
import { v1 } from 'node-uuid';
import { OrderService } from 'src/order/order.service';
import { isNumber, isNumberString } from 'class-validator';

@Injectable()
export class ProductService {
    constructor(
        @InjectRepository(Bk_Product)
        private readonly productRepository: Repository<Bk_Product>,
        @InjectRepository(Bk_Product_Info)
        private readonly productInfoRepository: Repository<Bk_Product_Info>,
        private readonly orderService: OrderService
    ) { }

    //单个添加文件
    async uploadFile(filePath: 'image' | 'video' | 'testPaper', fileName: string, buffer: string | NodeJS.ArrayBufferView) {
        fs.writeFileSync(join(__dirname, '..', 'public', filePath, fileName), buffer);
    }

    // 新增试卷
    async appendTestPaper(productName: string, testPaper: string, original_testPaper: string, productId: number) {
        const testPaperName = v1() + '.html';
        await this.uploadFile('testPaper', testPaperName, testPaper);
        await this.addProductInfo(productName, testPaperName, productId, original_testPaper)
    }
    // 添加一个商品信息
    async addProductInfo(product_name: string, product_url: string, productId: number, other?: string) {
        let otherKey = ''
        if (typeof other === 'string') {
            otherKey = 'original_testPaper';
        } else {
            otherKey = 'video';
        }
        return await this.productInfoRepository.save({
            product_name,
            product_url,
            [otherKey]: other,
            product: { id: productId }
        });
    }
    // 单个删除文件
    removeFile(filePath: 'image' | 'video' | 'testPaper', fileName: string) {
        fs.unlink(join(__dirname, '..', 'public', filePath, fileName), () => console.log(`删除 ${fileName} 成功！`));
    }

    async add(files: any, body: any): Promise<Bk_Product> {//添加商品
        console.log(files);
        console.log(body);

        const {
            product_name,
            product_description,
            product_price,
            product_type,
            subject,
            series,
            testPapers,
            videos,
            order_number
        } = body;
        const thumbnail_url = v1() + '.' + files.thumbnail[0].originalname.split('.')[1];
        const product = {
            thumbnail_url,
            product_name,
            product_description,
            product_price,
            product_type,
            subject,
            series,
            order_number
        }
        const { id } = await this.productRepository.save(product);
        let productInfo: any;
        if (product_type == 0) {//视频
            productInfo = JSON.parse(videos);
            let productInfoList = [];
            for (const key in productInfo) {
                productInfoList.push(productInfo[key]);
            }
            for (let i = 0; i < productInfoList.length; i++) {
                await this.addProductInfo(productInfoList[i].file_name, productInfoList[i].file_path, id, productInfoList[i])
            }
        } else {//试卷
            productInfo = JSON.parse(testPapers);
            let productInfoList = [];
            for (const key in productInfo) {
                productInfoList.push(productInfo[key]);
            }
            for (let i = 0; i < productInfoList.length; i++) {
                await this.appendTestPaper(productInfoList[i].testPaper_name, productInfoList[i].testPaper, productInfoList[i].original_testPaper, id);
            }
        }
        this.uploadFile('image', thumbnail_url, files.thumbnail[0].buffer);
        return await this.productRepository.findOne({ relations: ["subject", "series", "product_info"], where: { id } });
    }

    async delete(id: number): Promise<any> {//删除商品
        const order = await this.orderService.getOrderByProduct({ id });
        if (order.length <= 0) {//可以删除
            const { thumbnail_url, product_info, product_name } = await this.productRepository.findOne({ relations: ["product_info"], where: { id } });
            for (let i = 0; i < product_info.length; i++) {
                await this.productInfoRepository.delete({ product: { id } });
            }
            fs.unlink(join(__dirname, '..', 'public', 'image', thumbnail_url), () => console.log(`删除商品 ${product_name} 缩略图 ${thumbnail_url} 成功！`));
            return await this.productRepository.delete(id);
        } else {//有关联关系不能删除
            return order;
        }
    }

    async update(files: any, body: any): Promise<Bk_Product> {//更新商品
        const {
            id,
            product_name,
            product_description,
            product_price,
            product_type,
            subject,
            series,
            testPapers,
            videos,
            order_number
        } = body;
        await this.productRepository.update(id, {
            product_name,
            product_description,
            product_price,
            subject,
            series,
            order_number
        });
        // const product = await this.productRepository.findOne({ relations: ["product_info"], where: { id } });
        const product = await this.productRepository.createQueryBuilder('product')
            .leftJoinAndSelect('product.product_info', 'product_info')
            .where('product.id = :id', { id })
            .addSelect('product_info.product_url')
            .getOne()
        files.thumbnail && this.uploadFile('image', product.thumbnail_url, files.thumbnail[0].buffer);//更新缩略图
        let productInfo: any;
        let productInfoList = [];
        if (product_type != 0) {//试卷
            for (let i = 0; i < product.product_info.length; i++) {
                this.removeFile('testPaper', product.product_info[i].product_url);
                await this.productInfoRepository.delete(product.product_info[i].id);
            }
            productInfo = JSON.parse(testPapers);
            for (const key in productInfo) {
                productInfoList.push(productInfo[key]);
            }
            for (let i = 0; i < productInfoList.length; i++) {
                await this.appendTestPaper(productInfoList[i].testPaper_name, productInfoList[i].testPaper, productInfoList[i].original_testPaper, id);
            }

        } else {

            for (let i = 0; i < product.product_info.length; i++) {
                await this.productInfoRepository.delete(product.product_info[i].id);
            }
            productInfo = JSON.parse(videos);
            for (const key in productInfo) {
                productInfoList.push(productInfo[key]);
            }
            for (let i = 0; i < productInfoList.length; i++) {
                await this.addProductInfo(productInfoList[i].file_name, productInfoList[i].file_path, id, productInfoList[i])
            }

        }
        return await this.productRepository.findOne({ relations: ["subject", "series", "product_info", "product_info.video"], where: { id } });
    }

    async findAll(query: any): Promise<[Bk_Product[], number]> {
        
        
        const where: {
            subject?: { id: number }
            series?: { id: number }
            product_type?: number
        } = {};
        console.log(where);
        query.subjectId && (where.subject = { id: query.subjectId });
        query.seriesId && (where.series = { id: query.seriesId });
        query.product_type && (where.product_type = query.product_type);

        if(query.wechat_applets){
            return await this.productRepository.findAndCount({take:query.take,skip:query.skip,where:{product_type:query.product_type,product_price:Not(0)}})
        }
        return await this.productRepository.findAndCount({
        relations: ["subject", "series", "product_info", "product_info.video"],
        order: { order_number: "ASC" },
        skip: isNumber(query.skip) || isNumberString(query.skip) ? query.skip : undefined,
        take: isNumber(query.take) || isNumberString(query.take) ? query.take : undefined,
        where
        })
        
        
        
    }

    async getProductsByCategory(subject?: number, series?: number, product_type?: number): Promise<Bk_Product[]> {//分类查询
        return await this.productRepository.find({ relations: ["subject", "series", "product_info", "product_info.video"], where: { product_type, subject: { id: subject }, series: { id: series } } });
    }

    async getProductById(id: number): Promise<Bk_Product> {//按id查询
        const product = await this.productRepository.createQueryBuilder('product')
            .leftJoinAndSelect('product.subject', 'subject')
            .leftJoinAndSelect('product.series', 'series')
            .leftJoinAndSelect('product.product_info', 'product_info')
            .leftJoinAndSelect('product_info.video', 'video')
            .where('product.id = :id', { id })
            .addSelect('video.file_path').addSelect('product_info.product_url')
            .getOne();
        if (product?.product_price > 0) {
            product.product_info.forEach(item => {
                item.video.file_path = ''
                item.product_url = ''
            })
        }
        return product
    }
}